package com.example.student.service.impl;

import com.example.student.entity.SysUser;
import com.example.student.service.TokenService;
import io.jsonwebtoken.Claims;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.concurrent.TimeUnit;

/**
 * JWT令牌服务实现
 * 结合Redis缓存与JWT验证，实现TokenService接口
 */
@Service
public class JwtTokenServiceImpl implements TokenService {

    private static final String TOKEN_KEY_PREFIX = "token:";
    private static final long TOKEN_EXPIRE_TIME = 24; // 24小时

    @Resource
    private RedisTemplate<String, Object> redisTemplate;
    
    @Resource
    private JwtTokenService jwtTokenService;

    @Override
    public void saveToken(String userId, String token) {
        String key = TOKEN_KEY_PREFIX + userId;
        redisTemplate.opsForValue().set(key, token, TOKEN_EXPIRE_TIME, TimeUnit.HOURS);
    }

    @Override
    public String getToken(String userId) {
        String key = TOKEN_KEY_PREFIX + userId;
        Object token = redisTemplate.opsForValue().get(key);
        return token != null ? token.toString() : null;
    }

    @Override
    public void removeToken(String userId) {
        String key = TOKEN_KEY_PREFIX + userId;
        redisTemplate.delete(key);
    }

    @Override
    public boolean validateToken(String userId, String token) {
        String storedToken = getToken(userId);
        return token != null && token.equals(storedToken);
    }
    
    /**
     * 生成token并存入Redis
     */
    public String generateToken(SysUser user) {
        String token = jwtTokenService.generateToken(user);
        // 将token存入Redis
        saveToken(user.getId().toString(), token);
        return token;
    }
    
    /**
     * 生成刷新token
     */
    public String generateRefreshToken(SysUser user) {
        return jwtTokenService.generateRefreshToken(user);
    }
    
    /**
     * 从token中获取用户信息
     */
    public Claims getClaimsFromToken(String token) {
        return jwtTokenService.getClaimsFromToken(token);
    }
    
    /**
     * 从请求中获取token
     */
    public String getTokenFromRequest(HttpServletRequest request) {
        return jwtTokenService.getTokenFromRequest(request);
    }
    
    /**
     * 验证token
     */
    public boolean validateToken(String token) {
        try {
            // 首先验证JWT格式和签名
            boolean isValidJwt = jwtTokenService.validateToken(token);
            if (!isValidJwt) {
                return false;
            }
            
            // 然后验证是否在Redis中存在
            Claims claims = getClaimsFromToken(token);
            String userId = claims.getSubject();
            if (userId == null) {
                return false;
            }
            
            // 检查Redis中是否存在该token
            String storedToken = getToken(userId);
            return token.equals(storedToken);
        } catch (Exception e) {
            return false;
        }
    }
    
    /**
     * 将token加入黑名单
     */
    public void addToBlacklist(String token, Long userId) {
        // 从Redis中移除token
        if (userId != null) {
            removeToken(userId.toString());
        }
        
        // 同时加入数据库黑名单
        jwtTokenService.addToBlacklist(token, userId);
    }
    
    /**
     * 刷新token
     */
    public String refreshToken(String refreshToken) {
        try {
            Claims claims = jwtTokenService.getClaimsFromToken(refreshToken);
            String userId = claims.getSubject();
            
            // 生成新的访问token
            String newToken = jwtTokenService.refreshToken(refreshToken);
            
            // 将新token存入Redis
            if (newToken != null && userId != null) {
                saveToken(userId, newToken);
            }
            
            return newToken;
        } catch (Exception e) {
            return null;
        }
    }
} 